package cn.org.xuanguang.kepler.hormos.rdb.dml.operator.select;

import cn.org.xuanguang.kepler.hormos.rdb.dml.operator.DmlOperator;
import cn.org.xuanguang.kepler.hormos.rdb.dml.warrper.ResultWrapper;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.execute.Delete;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.execute.Query;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.param.Term;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.param.TermType;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.sql.SqlRequest;
import cn.org.xuanguang.kepler.hormos.rdb.executor.SyncSqlExecutor;
import cn.org.xuanguang.kepler.hormos.rdb.plugin.DmlSQLBuilder;
import lombok.Getter;

import java.util.Arrays;
import java.util.Collection;

public class SelectOperator<E, R> implements DmlOperator<SelectOperatorResulet> {
    // SyncSqlExecutor用于同步执行SQL命令
    private SyncSqlExecutor syncSqlExecutor;

    // dailatype用于指定数据库类型，影响数据库操作的执行方式
    private String dailatype;

    @Getter
    private ResultWrapper<SelectOperatorResulet, R> wrapper;
    /**
     * 入参
     */
    SelectOperatorParameter parameter;


    public SelectOperator(SyncSqlExecutor syncSqlExecutor, String dailatype, SelectOperatorParameter selectOperatorParameter) {
        this.syncSqlExecutor = syncSqlExecutor;
        this.dailatype = dailatype;
        this.parameter = selectOperatorParameter;

    }

    public static SelectOperator of(SyncSqlExecutor syncSqlExecutor, String dailatype, SelectOperatorParameter selectOperatorParameter) {
        return new SelectOperator(syncSqlExecutor, dailatype, selectOperatorParameter);
    }

    public SelectOperator from(String tableName) {
        parameter.setTableName(tableName);
        return this;
    }

    /**
     * 添加需要插入的列集合。
     *
     * @param columns 要添加的列的集合，不可为null。
     * @return 返回当前SelectOperator实例，允许链式调用。
     */
    public SelectOperator select(Collection<String> columns) {
        parameter.getColumns().addAll(columns);
        return this;
    }

    public SelectOperator select(String... columns) {
        parameter.getColumns().addAll(Arrays.asList(columns));
        return this;
    }


    // 查询条件
    public SelectOperator where(Delete delete) {
        parameter.getTerms().addAll(delete.getParam().getTerms());
        return this;
    }

    public SelectOperator where(Collection<? extends Term> terms) {
        parameter.getTerms().addAll(terms);
        return this;
    }

    public SelectOperator and(String column, String termType, Object value) {
        parameter.getTerms().addAll(Delete.of().and(column, termType, value).getParam().getTerms());
        return this;
    }
    public SelectOperator and(String column,  Object value) {
        parameter.getTerms().addAll(Delete.of().and(column, TermType.eq, value).getParam().getTerms());
        return this;
    }

    public SelectOperator or(String column, String termType, Object value) {
        parameter.getTerms().addAll(Delete.of().or(column, termType, value).getParam().getTerms());
        return this;
    }
    public SelectOperator or(String column,  Object value) {
        parameter.getTerms().addAll(Delete.of().or(column, TermType.eq, value).getParam().getTerms());
        return this;
    }

    // in
    public SelectOperator in(String column, Object... values) {
        parameter.getTerms().addAll(Query.of().in(column, values).getParam().getTerms());
        return this;
    }

    // not in
    public SelectOperator notIn(String column, Object... values) {
        parameter.getTerms().addAll(Query.of().notIn(column, values).getParam().getTerms());
        return this;
    }

    /**
     * 获取sql
     *
     * @return
     */
    @Override
    public SqlRequest getSql() {
        // 获取sql
        return DmlSQLBuilder.of(dailatype).buildSelect(parameter);

    }


    @Override
    public SelectOperatorResulet execute() {

        return SelectOperatorResulet.of(syncSqlExecutor.select(getSql(), getWrapper()));
    }

    public SelectOperator setWrapper(ResultWrapper<SelectOperatorResulet, R> wrapper) {
        this.wrapper = wrapper;
        return this;
    }
}
